package it.polito.connectedcar.vehicle;

import it.polito.connectedcar.tcc.zone.Token;

import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * the VehicleZone is the class which wraps the information about the zones the
 * vehicle knows about A vehicle use a neural network representation of the
 * vehicles it has to take into account. Thinking at the list of surrounding
 * vehicles as a connected graph in which all nodes are the vehicles and the
 * arcs are the link between the objects. Each arc has a weight which represents
 * the space distance between 2 vehicles.The weights of the arc continuously
 * change based on the fact that the vehicles are moving into the space.
 * </br></br>In order to avoid useless overhead due to some intensive
 * computations like collision warning, the frequency of message sending is
 * dictated by a priority index. The priority index is a grouping index
 * identifying a set of levels of distances between 2 vehicles. The more the
 * index is high , the more the vehicles are far each other , and the less is
 * the frequency of updates they exchange. By having the same model adopted by
 * all connected vehicles , we are sure that when 2 vehicles are near , they
 * sense the same distance, thus increasing the update frequency and better
 * monitor their relative speed and position.
 * 
 * 
 * @author Nicola Aresta
 * 
 */
public class VehicleZone {

	public static final int MINIMUM_PRIORITY = 6;
	public static final int MAXIMUM_PRIORITY = 0;
	public static final int DISTANCE_FOR_PRIORITY_LEVEL = 20; // meters
	private Token zoneToken;
	private InetSocketAddress tccAddress;
	private int currentPriorityForSending = MAXIMUM_PRIORITY;

	private ConcurrentHashMap<Integer, CopyOnWriteArraySet<InetSocketAddress>> prioritizedVehicles;
	private CopyOnWriteArraySet<InetSocketAddress> vehicles;

	public VehicleZone() {
		vehicles = new CopyOnWriteArraySet<InetSocketAddress>();
		prioritizedVehicles = new ConcurrentHashMap<Integer, CopyOnWriteArraySet<InetSocketAddress>>();
		/* full inizialization */
		for (int i = MAXIMUM_PRIORITY; i <= MINIMUM_PRIORITY; i++) {
			prioritizedVehicles.put(i,
					new CopyOnWriteArraySet<InetSocketAddress>());
		}
	}

	public VehicleZone(InetSocketAddress tccAddress, Token t) {
		this();
		this.tccAddress = tccAddress;
		this.zoneToken = t;
	}

	public InetSocketAddress getTccAddress() {
		return tccAddress;
	}

	public void setTccAddress(InetSocketAddress tccAddress) {
		this.tccAddress = tccAddress;
	}

	public CopyOnWriteArraySet<InetSocketAddress> getVehicles() {
		return vehicles;
	}

	public Token getZoneToken() {
		return zoneToken;
	}

	public void setZoneToken(Token zoneToken) {
		this.zoneToken = zoneToken;
	}

	@Override
	public boolean equals(Object obj) {
		Token t = null;

		if ((obj instanceof VehicleZone))
			t = ((VehicleZone) obj).getZoneToken();
		else if ((obj instanceof Token))
			t = (Token) obj;

		return t == null ? false : t.equals(zoneToken);
	}

	public ConcurrentHashMap<Integer, CopyOnWriteArraySet<InetSocketAddress>> getPrioritizedVehicles() {
		return prioritizedVehicles;
	}

	public void setPrioritizedVehicles(
			ConcurrentHashMap<Integer, CopyOnWriteArraySet<InetSocketAddress>> prioritizedVehicles) {
		this.prioritizedVehicles = prioritizedVehicles;
	}

	public synchronized int getCurrentPriorityForSending() {
		return currentPriorityForSending;
	}

	public synchronized void updatePriorityCounter() {
		currentPriorityForSending = (currentPriorityForSending == MINIMUM_PRIORITY
				? 0
				: currentPriorityForSending++);
	}
}
